#include <stdio.h>
#include <sys/socket.h>
#include <errno.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <getopt.h>

void printf_help(char *progname )
{
	printf("%s usage:\n",progname);
	printf("-p(--port):sepcify listen port\n");
	printf("-h(--help):print this help information\n");
}

int main(int argc,char **argv)
{

	int                   cli_fd=-1;
	int                   lis_fd=-1;
	struct   sockaddr_in  serv_addr;
	struct   sockaddr_in  cli_addr;
	int                       rv=-1;
	int                  lis_port=0;
	char                  buf[128];
	int                 *index=NULL;
	int                          ch;
	int                       on=1;
	socklen_t          cli_addr_len;

	struct  option  opts[]={
	
		{"port",required_argument,NULL,'p'},
		{"help",no_argument,NULL,'h'},
		{0,0,0,0}
	};



	while( (ch=getopt_long(argc,argv,"p:h",opts,index)) != -1  )
	{
		switch(ch)
		{
			case'p':
				lis_port=atoi(optarg);
				break;
			case'h':
				printf_help(argv[0]);
				return 0;
		}
	}

	if( !lis_port  )
	{
		printf_help(argv[0]);
		return -1;
	
	}

	lis_fd=socket(AF_INET,SOCK_STREAM,0);
	if(lis_fd<0)
	{
		printf("create socket failure:%s\n",strerror(errno));
		return -1;
	}
	printf("create socket [%d] successfully!\n",lis_fd);


	//setsockopt(lis_fd,SOL_SOCKET,SO_REUSEADDR,(const void *)&opt, sizeof(opt));
	setsockopt(lis_fd,SOL_SOCKET,SO_REUSEADDR,&on, sizeof(on));
	//定义服务器协议以及地址，端口
	memset(&serv_addr,0,sizeof(serv_addr));
	serv_addr.sin_family = AF_INET;
	serv_addr.sin_port  = htons(lis_port);
	serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);  

	printf("serv_addr.sin_port:%d\n",ntohs(cli_addr.sin_port));
//	printf("serv_addr.sin_addr:%s\n",ntohs(cli_addr.sin_port));
	
	rv=bind(lis_fd,(struct sockaddr *)&serv_addr,sizeof(serv_addr));
	if(rv<0)
	{
		printf("bind [%d] failure:%s\n",lis_fd,strerror(errno));
		return -2;
	}
	printf("bind PORT: [%d] successfully\n",ntohs(serv_addr.sin_port));

	rv=listen(lis_fd,13);
	if(rv<0)
	{
		printf("listen [%d] failure:%s\n",lis_fd,strerror(errno));
		return -1;	
	}
	printf("server is listenning the port [%d]\n",ntohs(serv_addr.sin_port));

//	memset(&cli_addr,0,sizeof(cli_addr));
	cli_addr_len=sizeof(cli_addr);
	while(1)	
	{
		printf("waiting new client accept....\n");
	
		cli_fd=accept(lis_fd,(struct sockaddr *)&cli_addr,&cli_addr_len);
		
//		printf("cli_addr.sin_port:%d\n",ntohs(cli_addr.sin_port));
//		printf("cli_addr.sin_addr.s_addr:%s\n",inet_ntoa(cli_addr.sin_addr));
		
		if(cli_fd<0)
		{
			printf("accept lis_fd [%d] failure:%s\n",lis_fd,strerror(errno));
			continue;
		}
		printf("accept [%d] client [IP:%s PORT:%d] successfully\n",cli_fd,inet_ntoa(cli_addr.sin_addr),ntohs(cli_addr.sin_port));//?

                memset(buf,0,sizeof(buf));
	       	rv=read(cli_fd,buf,sizeof(buf));
		if(rv<0)
		{
			printf("read failure:%s\n",strerror(errno));
			break;
		}
		else if(rv==0)
		{
			printf("connect server break\n");
			continue;
		}
		printf("read data %d byte:%s\n",rv,buf);


		rv=write(cli_fd,buf,strlen(buf));
		if(rv<0)
		{
			printf("write to client failure:%s\n",strerror(errno));
			break;
		}
		printf("write '%s' data %d byte back to client successfully\n",buf,rv);
	
	} 

	close(cli_fd);
	close(lis_fd);
	return 0;
}
